﻿// <copyright file="TagCollection.cs" company="Signal Processing Lab, Wuhan University">
// Copyright (c) 2009-2010 All Right Reserved
// </copyright>
// <author>Xinping Deng</author>
// <email>dentoby@gmail.com</email>
// <date>2010-4</date>
// <summary>This is part of Image.NET project.</summary>

namespace SPLWHU.Core
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// The collection of <see cref="Tag"/>s. The information exchange between GUI and appliction class is based on this class.
    /// </summary>
    public class TagCollection : Tag, ICollection<Tag>
    {
        /// <summary>
        /// The <see cref="Tag"/>s stored in this collecion.
        /// </summary>
        private List<Tag> tags;

        /// <summary>
        /// Initializes a new instance of the <see cref="TagCollection"/> class.
        /// </summary>
        /// <param name="name">The name of this tag.</param>
        public TagCollection(string name)
        {
            this.Name = name;
            this.tags = new List<Tag>();
        }

        /// <summary>
        /// Gets or sets a value indicating whether the value is read only or not.
        /// </summary>
        /// <value><c>true</c>, if [Read Only]; otherwise, <c>false</c>.</value>
        public override bool ReadOnly
        {
            get
            {
                return base.ReadOnly;
            }

            set
            {
                // Sets the [ReadOnly] of tags in this collection.
                foreach (Tag t in this.tags)
                {
                    t.ReadOnly = value;
                }

                // Sets the [ReadOnly] of this instance. 
                base.ReadOnly = value;
            }
        }

        /// <summary>
        /// Gets the count of tags in this collection.
        /// </summary>
        public int Count
        {
            get { return this.tags.Count; }
        }

        /// <summary>
        /// Gets the type of value stored in this tag.
        /// </summary>
        /// <value>The tag type.</value>
        public override Type ValueType
        {
            get { return typeof(TagCollection); }
        }

        /// <summary>
        /// Gets or sets the tag by a name.
        /// </summary>
        /// <param name="name">The name of the tag</param>
        /// <returns>The named tag</returns>
        public Tag this[string name]
        {
            get
            {
                // Loops on the count of all tags.
                for (int i = 0, count = this.tags.Count; i < count; i++)
                {
                    Tag t = this.tags[i];

                    if (t.Name == name)
                    {
                        return t;
                    }
                }

                // There is no tag having the name [name].
                return null;
            }

            set
            {
                // Gets the index of property having name [name].
                int index = -1;
                for (int i = 0, count = this.tags.Count; i < count; i++)
                {
                    if (this.tags[i].Name == name)
                    {
                        index = i;
                        break;
                    }
                }

                // Sets the value.
                if (index >= 0)
                {
                    this.tags[index] = value;
                }
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="Tag"/> at the specified index.
        /// </summary>
        /// <param name="index">The index of tag.</param>
        /// <returns>The tag at the specified index.</returns>
        public Tag this[int index]
        {
            get
            {
                if (index >= 0 && index < this.tags.Count)
                {
                    return this.tags[index];
                }
                else
                {
                    return null;
                }
            }

            set
            {
                if (index >= 0 && index < this.tags.Count)
                {
                    this.tags[index] = value;
                }
            }
        }

        /// <summary>
        /// Converts this colletion to an array.
        /// </summary>
        /// <returns>The array stores all <see cref="Tag"/>s.</returns>
        public Tag[] ToArray()
        {
            return this.tags.ToArray();
        }

        /// <summary>
        /// Converts the value of this instance to text.
        /// </summary>
        /// <returns>Converted text representing the value.</returns>
        public override string ValueToText()
        {
            return string.Empty;
        }

        /// <summary>
        /// Parses the value of this instance from text.
        /// </summary>
        /// <param name="text">The text to be parsed to generate value.</param>
        public override void ValueFromText(string text)
        {
            // do nothing.
        }

        /// <summary>
        /// Retrives the value in this tag.
        /// </summary>
        /// <returns>The value stored in this tag.</returns>
        public override object GetValue()
        {
            return null;
        }

        /// <summary>
        /// Resets the value to default value.
        /// </summary>
        public override void ResetValue()
        {
            foreach (Tag t in this.tags)
            {
                t.ResetValue();
            }
        }

        #region ICollection<Tag> 成员

        /// <summary>
        /// Add a <see cref="Tag"/> to this collection.
        /// </summary>
        /// <param name="value">The tag to be added.</param>
        public void Add(Tag value)
        {
            this.tags.Add(value);
        }

        /// <summary>
        /// Adds several tags.
        /// </summary>
        /// <param name="values">The tags to be added.</param>
        public void Add(params Tag[] values)
        {
            this.tags.AddRange(values);
        }

        /// <summary>
        /// Remove a tag from the collection.
        /// </summary>
        /// <param name="tag">The tag to be removed</param>
        public void Remove(Tag tag)
        {
            this.tags.Remove(tag);
        }

        /// <summary>
        /// Removes the tag at the specified index.
        /// </summary>
        /// <param name="index">The index of the tag to be reomved.</param>
        public void RemoveAt(int index)
        {
            if (index >= 0 && index < this.tags.Count)
            {
                this.tags.RemoveAt(index);
            }
        }

        /// <summary>
        /// Clears the collection.
        /// </summary>
        public void Clear()
        {
            this.tags.Clear();
        }

        /// <summary>
        /// Adds a list of items to the collection.
        /// </summary>
        /// <param name="items">The items to add.</param>
        public void Add(List<Tag> items)
        {
            foreach (Tag t in items)
            {
                this.tags.Add(t);
            }
        }

        /// <summary>
        /// Adds the items to the collection.
        /// </summary>
        /// <param name="items">The items to add.</param>
        public void Add(IEnumerable<Tag> items)
        {
            foreach (Tag t in items)
            {
                this.tags.Add(t);
            }
        }

        /// <summary>
        /// Inserts an item at the specified index.
        /// </summary>
        /// <param name="index">The index to insert.</param>
        /// <param name="item">The item to add.</param>
        public void Insert(int index, Tag item)
        {
            this.tags.Insert(index, item);
        }

        /// <summary>
        /// Enumerates the items in this instance.
        /// </summary>
        /// <returns>
        /// The enumerator to access the items in this collection.
        /// </returns>
        public IEnumerable<Tag> Enumerate()
        {
            return this.tags;
        }

        #endregion
    }
}
